/*
 * PlayerPanel.java
 *
 * Created on January 17, 2005, 11:00 PM
 */
package com.bff.mpd.musicjukebox.ui;

import com.bff.mpd.musicjukebox.lib.JukeboxProperties;
import com.bff.mpd.musicjukebox.lib.actions.MuteAction;
import com.bff.mpd.musicjukebox.lib.actions.NextAction;
import com.bff.mpd.musicjukebox.lib.actions.PauseAction;
import com.bff.mpd.musicjukebox.lib.actions.PlayAction;
import com.bff.mpd.musicjukebox.lib.actions.PrevAction;
import com.bff.mpd.musicjukebox.lib.actions.StopAction;
import com.bff.bjj.ui.component.BJJPanel;
import com.bff.mpd.musicjukebox.ui.components.PlayerJPanel;
import com.bff.mpd.utils.Utils;
import java.awt.Color;
import java.awt.Component;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.bff.javampd.MPDPlayer;
import org.bff.javampd.events.PlayerBasicChangeEvent;
import org.bff.javampd.events.PlayerBasicChangeListener;
import org.bff.javampd.events.PlayerChangeEvent;
import org.bff.javampd.events.PlayerChangeListener;
import org.bff.javampd.exception.MPDConnectionException;
import org.bff.javampd.exception.MPDPlayerException;
import org.bff.javampd.objects.MPDSong;

/**
 *
 * @author Bill
 */
public class PlayerPanel
        extends PlayerJPanel
        implements PlayerBasicChangeListener,
        PlayerChangeListener {

    private Action playAction;
    private Action stopAction;
    private Action pauseAction;
    private Action prevAction;
    private Action nextAction;
    private Action muteAction;
    private MPDPlayer player;
    private long totalTrackTime = 0;
    private Color gradientColor;

    /** Creates new form PlayerPanel */
    public PlayerPanel() {
            gradientColor = Color.GRAY;
            setPlayer(JukeboxProperties.getInstance().getPlayer());

            makeActions();
            initComponents();
            try {
                volumeSlider.setValue(getPlayer().getVolume());
            } catch (MPDConnectionException ex) {
                Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (MPDPlayerException ex) {
                Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
            }

            JukeboxProperties.getInstance().getMPDMonitor().addPlayerChangeListener(this);
            JukeboxProperties.getInstance().getPlayer().addPlayerChangeListener(this);

            volumeSlider.addChangeListener(new ChangeListener() {

                public void stateChanged(ChangeEvent ce) {
                    try {
                        getPlayer().setVolume(volumeSlider.getValue());
                    } catch (MPDConnectionException ex) {
                        Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (MPDPlayerException ex) {
                        Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
        }
    

    //Contructor that creates menu bar options
    //Same abstract action for buttons and menu
    public PlayerPanel(JMenuBar menuBar) {
        makeActions();
        initComponents();

        JMenu playMenu = new JMenu("Player");

        playMenu.add(new JMenuItem(prevAction));
        playMenu.add(new JMenuItem(pauseAction));
        playMenu.add(new JMenuItem(stopAction));
        playMenu.add(new JMenuItem(playAction));
        playMenu.add(new JMenuItem(nextAction));

        menuBar.add(playMenu);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        playerStatusPanel = new javax.swing.JPanel();
        playerInfoPanel = new BJJPanel();
        jPanel2 = new BJJPanel();
        statusLabel = new javax.swing.JLabel();
        timeLabel = new javax.swing.JLabel();
        songInfoPanel = new SongInfoPanel();
        volumePanel = new BJJPanel();
        volumeSlider = new javax.swing.JSlider();
        btnMute = new javax.swing.JButton(muteAction);
        btnMute.setText(null);
        jPanel1 = new BJJPanel();
        timeSlider = new javax.swing.JSlider();
        totalTimeLabel = new javax.swing.JLabel();
        playerButtonPanel = new BJJPanel();
        btnPrev = new javax.swing.JButton(prevAction);
        btnPrev.setText(null);
        btnPause = new javax.swing.JButton(pauseAction);
        btnPause.setText(null);
        btnStop = new javax.swing.JButton(stopAction);
        btnStop.setText(null);
        btnPlay = new javax.swing.JButton(playAction);
        btnPlay.setText(null);
        btnNext = new javax.swing.JButton(nextAction);
        btnNext.setText(null);

        setBorder(javax.swing.BorderFactory.createEmptyBorder(10, 10, 10, 10));
        setMaximumSize(new java.awt.Dimension(280, 250));
        setPreferredSize(new java.awt.Dimension(280, 220));
        setLayout(new java.awt.BorderLayout());

        playerStatusPanel.setBackground(java.awt.Color.lightGray);
        playerStatusPanel.setMaximumSize(new java.awt.Dimension(303, 25));
        playerStatusPanel.setPreferredSize(new java.awt.Dimension(202, 200));
        playerStatusPanel.setLayout(new java.awt.BorderLayout());

        playerInfoPanel.setBackground(java.awt.Color.lightGray);
        playerInfoPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        playerInfoPanel.setForeground(java.awt.Color.blue);
        playerInfoPanel.setLayout(new java.awt.BorderLayout());

        jPanel2.setBackground(java.awt.Color.lightGray);

        statusLabel.setBackground(java.awt.Color.lightGray);
        statusLabel.setForeground(java.awt.Color.blue);
        statusLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        statusLabel.setText("Stopped");
        statusLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
        jPanel2.add(statusLabel);

        timeLabel.setBackground(java.awt.Color.lightGray);
        timeLabel.setFont(new java.awt.Font("MS Sans Serif", 0, 18));
        timeLabel.setForeground(java.awt.Color.blue);
        timeLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        timeLabel.setText("0:00");
        jPanel2.add(timeLabel);

        playerInfoPanel.add(jPanel2, java.awt.BorderLayout.SOUTH);
        playerInfoPanel.add(songInfoPanel, java.awt.BorderLayout.CENTER);

        playerStatusPanel.add(playerInfoPanel, java.awt.BorderLayout.CENTER);

        volumePanel.setLayout(new java.awt.BorderLayout());

        volumeSlider.setBackground(java.awt.Color.lightGray);
        volumeSlider.setForeground(java.awt.Color.blue);
        volumeSlider.setMajorTickSpacing(25);
        volumeSlider.setMinorTickSpacing(5);
        volumeSlider.setOrientation(javax.swing.JSlider.VERTICAL);
        volumeSlider.setPaintTicks(true);
        volumeSlider.setValue(100);
        volumeSlider.setMinimumSize(new java.awt.Dimension(100, 25));
        volumeSlider.setPreferredSize(new java.awt.Dimension(25, 25));
        volumePanel.add(volumeSlider, java.awt.BorderLayout.EAST);

        btnMute.setBackground(java.awt.Color.lightGray);
        btnMute.setBorder(null);
        btnMute.setMaximumSize(new java.awt.Dimension(50, 50));
        btnMute.setMinimumSize(new java.awt.Dimension(32, 32));
        btnMute.setPreferredSize(new java.awt.Dimension(24, 24));
        volumePanel.add(btnMute, java.awt.BorderLayout.SOUTH);

        playerStatusPanel.add(volumePanel, java.awt.BorderLayout.EAST);

        jPanel1.setBackground(java.awt.Color.lightGray);
        jPanel1.setLayout(new java.awt.BorderLayout());

        timeSlider.setBackground(java.awt.Color.lightGray);
        timeSlider.setForeground(java.awt.Color.blue);
        timeSlider.setValue(0);
        timeSlider.setMaximumSize(new java.awt.Dimension(180, 24));
        timeSlider.setPreferredSize(new java.awt.Dimension(180, 24));
        jPanel1.add(timeSlider, java.awt.BorderLayout.CENTER);

        totalTimeLabel.setBackground(java.awt.Color.lightGray);
        totalTimeLabel.setForeground(new java.awt.Color(51, 51, 255));
        totalTimeLabel.setText("0:00");
        jPanel1.add(totalTimeLabel, java.awt.BorderLayout.EAST);

        playerStatusPanel.add(jPanel1, java.awt.BorderLayout.SOUTH);

        add(playerStatusPanel, java.awt.BorderLayout.CENTER);

        playerButtonPanel.setBackground(java.awt.Color.lightGray);
        playerButtonPanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        playerButtonPanel.setForeground(java.awt.Color.blue);
        playerButtonPanel.setMinimumSize(new java.awt.Dimension(155, 35));
        playerButtonPanel.setPreferredSize(new java.awt.Dimension(155, 55));
        playerButtonPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 0, 0));

        btnPrev.setBackground(java.awt.Color.lightGray);
        btnPrev.setBorder(null);
        btnPrev.setMaximumSize(new java.awt.Dimension(50, 50));
        btnPrev.setMinimumSize(new java.awt.Dimension(32, 32));
        btnPrev.setPreferredSize(new java.awt.Dimension(32, 32));
        playerButtonPanel.add(btnPrev);

        btnPause.setBackground(java.awt.Color.lightGray);
        btnPause.setBorder(null);
        btnPause.setMaximumSize(new java.awt.Dimension(50, 50));
        btnPause.setMinimumSize(new java.awt.Dimension(32, 32));
        btnPause.setPreferredSize(new java.awt.Dimension(32, 32));
        playerButtonPanel.add(btnPause);

        btnStop.setBackground(java.awt.Color.lightGray);
        btnStop.setBorder(null);
        btnStop.setMaximumSize(new java.awt.Dimension(50, 50));
        btnStop.setMinimumSize(new java.awt.Dimension(32, 32));
        btnStop.setPreferredSize(new java.awt.Dimension(32, 32));
        playerButtonPanel.add(btnStop);

        btnPlay.setBackground(java.awt.Color.lightGray);
        btnPlay.setBorder(null);
        btnPlay.setMaximumSize(new java.awt.Dimension(50, 50));
        btnPlay.setMinimumSize(new java.awt.Dimension(32, 32));
        btnPlay.setPreferredSize(new java.awt.Dimension(32, 32));
        playerButtonPanel.add(btnPlay);

        btnNext.setBackground(java.awt.Color.lightGray);
        btnNext.setBorder(null);
        btnNext.setMaximumSize(new java.awt.Dimension(50, 50));
        btnNext.setMinimumSize(new java.awt.Dimension(32, 32));
        btnNext.setPreferredSize(new java.awt.Dimension(32, 32));
        playerButtonPanel.add(btnNext);

        add(playerButtonPanel, java.awt.BorderLayout.SOUTH);
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnMute;
    private javax.swing.JButton btnNext;
    private javax.swing.JButton btnPause;
    private javax.swing.JButton btnPlay;
    private javax.swing.JButton btnPrev;
    private javax.swing.JButton btnStop;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel playerButtonPanel;
    private javax.swing.JPanel playerInfoPanel;
    private javax.swing.JPanel playerStatusPanel;
    private javax.swing.JPanel songInfoPanel;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JLabel timeLabel;
    private javax.swing.JSlider timeSlider;
    private javax.swing.JLabel totalTimeLabel;
    private javax.swing.JPanel volumePanel;
    private javax.swing.JSlider volumeSlider;
    // End of variables declaration//GEN-END:variables

    public void makeToolbar(JMenuBar menuBar) {
        makeToolbar(menuBar, -1);
    }

    public void makeToolbar(JMenuBar menuBar, int index) {
        JMenu playMenu = new JMenu("Player");
        playMenu.add(new JMenuItem(prevAction));
        playMenu.add(new JMenuItem(pauseAction));
        playMenu.add(new JMenuItem(stopAction));
        playMenu.add(new JMenuItem(playAction));
        playMenu.add(new JMenuItem(nextAction));
        playMenu.add(new JMenuItem(muteAction));
        menuBar.add(playMenu, index);
    }

    private void makeActions() {
        playAction = new PlayAction(getPlayer());
        stopAction = new StopAction(getPlayer());
        pauseAction = new PauseAction(getPlayer());
        prevAction = new PrevAction(getPlayer());
        nextAction = new NextAction(getPlayer());
        muteAction = new MuteAction(getPlayer());
    }

    protected JFrame getParentComponent(Component component) {
        if (component instanceof JPopupMenu) {
            component = ((JPopupMenu) component).getInvoker();
        }
        Component parent = component.getParent();
        if (parent instanceof JPopupMenu) {
            component = ((JPopupMenu) parent).getInvoker();
            parent = component.getParent();
        }
        while (!(parent instanceof JFrame) && (parent != null)) {
            parent = parent.getParent();
        }

        return (JFrame) parent;
    }

    public void setState(String state) {
        statusLabel.setText(state);
    }

    public void setElapsedTrackTime(long seconds) {
        if (seconds <= totalTrackTime) {
            timeLabel.setText(Utils.formatTime(seconds));
            timeSlider.setValue((int) seconds);
        }
    }

    public void setTotalTrackTime(long seconds) {
        totalTrackTime = seconds;
        totalTimeLabel.setText(Utils.formatTime(seconds));
        timeSlider.setMaximum((int) seconds);
    }

    @Override
    public void playerBasicChange(PlayerBasicChangeEvent event) {
        switch (event.getId()) {
            case (PlayerBasicChangeEvent.PLAYER_STOPPED):
                getSongInfoPanel().setSongInfo(null);
                statusLabel.setText("Stopped");
                setElapsedTrackTime(0);
                break;
            case (PlayerBasicChangeEvent.PLAYER_STARTED):
                songChange();
                break;
            case (PlayerBasicChangeEvent.PLAYER_PAUSED):
                statusLabel.setText("Paused");
                break;
            case (PlayerBasicChangeEvent.PLAYER_BITRATE_CHANGE):
                try {
                    getSongInfoPanel().setBitrate(getPlayer().getBitrate());
                } catch (MPDConnectionException ex) {
                    Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
                } catch (MPDPlayerException ex) {
                    Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void playerChanged(PlayerChangeEvent event) {
        switch (event.getId()) {
            case (PlayerChangeEvent.PLAYER_NEXT):
                songChange();
                break;
            case (PlayerChangeEvent.PLAYER_PREVIOUS):
                break;
            case (PlayerChangeEvent.PLAYER_MUTED):
                volumeSlider.setEnabled(false);
                break;
            case (PlayerChangeEvent.PLAYER_UNMUTED):
                volumeSlider.setEnabled(true);
                break;

        }
    }

    protected void songChange() {
        try {
            MPDSong song = getPlayer().getCurrentSong();
            if (song != null) {
                statusLabel.setText("Playing");
                setTotalTrackTime(song.getLength());
                getSongInfoPanel().setSongInfo(song);
            }
        } catch (MPDConnectionException ex) {
            Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MPDPlayerException ex) {
            Logger.getLogger(PlayerPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //to force song change when abve events arent enough
    public void setSong(MPDSong song) {
        setTotalTrackTime(song.getLength());
        getSongInfoPanel().setSongInfo(song);
    }

    public SongInfoPanel getSongInfoPanel() {
        return (SongInfoPanel) songInfoPanel;
    }

    /**
     * @return the player
     */
    public MPDPlayer getPlayer() {
        return player;
    }

    /**
     * @param player the player to set
     */
    public void setPlayer(MPDPlayer player) {
        this.player = player;
    }
}
